<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/6/8 0008
 * Time: 15:34
 */

namespace app\api\controller\v1\member;


use app\api\controller\v1\Member;
use app\currency\service\CitiesService;
use app\currency\service\CleanerService;
use app\currency\service\TimeSlotService;
use app\currency\service\WechatTemplateService;
use app\wechat\service\WechatService;
use library\tools\Data;
use think\Db;
use think\exception\HttpResponseException;

/**
 * 服务订单类
 * Class Order
 * @package app\api\controller\v1
 */
class Order extends Member
{
    /**
     * 获取订单列表 不传status获取全部订单0全部,1待接单,2待服务,3待支付,4已完成（包含待评价和已完成订单）
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function index()
    {
        $status = (int)$this->request->get('status',0);
        in_array($status,[0,1,2,3,4]) || $status = 0;
        if($status > 0){
            $where = [['status','eq',$status]];
        }
        $where[] = ['mid','eq',$this->mid];
        $where[] = ['is_deleted','eq','0'];
        $query = $this->_query('CleanOrder')
            ->where($where);
        $list = $query->order('create_at desc')->page(true,false,false,10);
        $cleaner_list = Db::name('Cleaner')
            ->where('id','in',array_unique(array_column($list['list'],'cid')))
            ->field('id,phone,name,work_headimg')
            ->select();
        foreach ($list['list'] as &$item) {
            $item['address_txt'] = CitiesService::getAddressText($item['cities_id'],'string');
            $item['cleaner'] = [];
            foreach ($cleaner_list as $cleaner) if($cleaner['id'] === $item['cid']) {
                $item['cleaner'] = $cleaner;
            }
        }
        $this->success('获取订单列表成功！',$list);
    }

    /**
     * 获取订单详情
     * @param $id
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function read($id)
    {

        $where =[['mid','eq',$this->mid],['order_no','eq',$id],['is_deleted','eq',0]];
        //订单信息
        $order = Db::name('CleanOrder')->where($where)->find();
        empty($order) && $this->error('订单信息查询失败！');
        $order['cleaner'] = [];
        if($order['cid'] > 0)
        {
            $order['cleaner'] = Db::name('Cleaner')->where(['id'=>$order['cid']])->find();
        }
        $order['unit_price'] = sysconf('service_unit_price');
        $order['address_txt'] = CitiesService::getAddressText($order['cities_id'],'string');
        //计算赠送积分
        $order['present_integral']=0;
        if($order['is_no_complete'] != 1)
        {
            $PresentIntegralSwitch = sysconf('present_integral_switch');
            if($PresentIntegralSwitch)
            {
                if(!empty($order['cleaner']) && $order['cleaner']['integral_present_num'] > 0)
                {
                    $PresentIntegralRatio = sysconf('present_integral_ratio') ?: 0;
                    if($PresentIntegralRatio > 0)
                    {
                        $order['present_integral'] = floor($order['total_price'] * $PresentIntegralRatio);
                    }
                }
            }
        }
        $this->success('获取订单详情成功！',$order);
    }

    /**
     * 创建订单页面数据
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function create()
    {
        $cities_id = $this->request->get('cities_id');
        is_numeric($cities_id) || $this->error('请选择正确的地址！');
        if(Db::name('Cities')->where('id',$cities_id)->count() < 1){
            $this->error('地址信息查询错误！');
        }
        //查询喜爱的保洁员
        $recommend_cleaner_record = (array)Db::name('MemberEnjoy')
            ->alias('a')
            ->where('mid','eq',$this->mid)
            ->whereNotExists("SELECT `b`.`mid` FROM `member_blacklist` `b` WHERE `a`.`mid` = `b`.`mid` AND `a`.`cid` = `b`.`cid`")
            ->field(true)
            ->order('create_at desc')
            ->limit(1)
            ->find();
        //如果不存在喜爱的保洁员则默认推荐该地址绑定保洁员
        if(empty($recommend_cleaner_record))
        {
            $recommend_cleaner_record = (array)Db::name('CitiesCleaner')
                ->alias('a')
                ->where('cities_id','eq',$cities_id)
                ->whereNotExists("SELECT `b`.`mid` FROM `member_blacklist` `b` WHERE `b`.`mid` = '{$this->mid}' AND `a`.`cid` = `b`.`cid`")
                ->field(true)
                ->limit(1)
                ->find();
        }
        $recommend_cleaner = [];
        if(!empty($recommend_cleaner_record) && isset($recommend_cleaner_record['cid'])){
            $recommend_cleaner = Db::name('Cleaner')
                ->where('id',$recommend_cleaner_record['cid'])
                ->field('id,phone,name,work_headimg')
                ->find();
        }
        $time_slot = [
            ['week' => '1','time_slot' => '1,2,3,4,5'],
            ['week' => '2','time_slot' => '1,2,3,4,5'],
            ['week' => '3','time_slot' => '1,2,3,4,5'],
            ['week' => '4','time_slot' => '1,2,3,4,5'],
            ['week' => '5','time_slot' => '1,2,3,4,5'],
            ['week' => '6','time_slot' => '1,2,3,4,5'],
            ['week' => '7','time_slot' => '1,2,3,4,5'],
        ];
        if(!empty($recommend_cleaner))
        {
            $time_slot = CleanerService::getAvailableTimeSlot($recommend_cleaner['id']);
        }
        $this->success('success',[
            'cleaner' => $recommend_cleaner,
            'time_slot' => $time_slot,
            'unit_price' => sysconf('service_unit_price'),
            'service_duration' => Db::name('Cities')->where('id',$cities_id)->value('service_duration')
        ]);
    }

    /**
     * 创建服务订单
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function save()
    {
        $data = $this->_input([
            'cities_id' => $this->request->post('cities_id'),
            'appoint_cid' => $this->request->post('appoint_cid',0),
            'service_date' => $this->request->post('service_date'),
            'time_slot' => $this->request->post('time_slot'),
        ],[
            'cities_id' => 'require|number',
            'appoint_cid' => 'number',
            'service_date' => 'require|date',
            'time_slot' => 'require|number'
        ],[
            'cities_id.require' => '请选择地址！',
            'cities_id.number' => '地址格式出错！',
            'appoint_cid.number' => '指定保洁员错误！',
            'service_date.require' => '请选择服务日期！',
            'service_date.date' => '服务日期格式错误！',
            'time_slot.require' => '请选择服务时间！',
            'time_slot.number' => '服务时间格式出错！',
        ]);
        //验证地址是否正确
        $cities_member = Db::name('CitiesMember')->where([['mid','eq',$this->mid],['cities_id','eq',$data['cities_id']]])->find();
        empty($cities_member) && $this->error('查询用户地址信息失败！');
        $cities = Db::name('Cities')->where('id',$data['cities_id'])->find();
        empty($cities) && $this->error('地址信息查询失败！');

        //获取服务时间
        $time_slot = TimeSlotService::getTimeSlot($data['time_slot']);
        if($time_slot === ''){
            $this->error('请选择正确的服务时间！');
        }
        $order = [
            'mid' => $this->mid,
            'appoint_cid' => $data['appoint_cid'],
            'order_no' => Data::uniqidNumberCode(12),
            'service_date' => $data['service_date'],
            'time_slot' => $data['time_slot'],
            'cities_id' => $data['cities_id'],
            'contact_name' => $cities_member['contact_name'],
            'contact_phone' => $cities_member['contact_phone'],
            'cities_center' => $cities['center']
        ];
        $unit_price = sysconf('service_unit_price');
        if(empty($unit_price))
        {
            $this->error('请先设置服务单价！');
        }
        if($cities['service_duration'] > 0)
        {
            $order['service_duration'] = $cities['service_duration'];
            //计算订单总价
            $order['total_price'] = $order['service_duration'] * $unit_price;
            //订单待支付金额
            $order['actual_amount'] = $order['total_price'];
        } else {
            $order['is_no_complete'] = 1;
        }
        try {
            // 订单数据写入
            Db::name('CleanOrder')->insert($order);
            //插入模板消息
            WechatTemplateService::sendOrderCreate($this->member->openid, $order['order_no'], $order['contact_name'], $order['contact_phone']);
            // 待接单订单提醒（保洁员）
            $FreeCleaner = CleanerService::getFreeCleaner($data['service_date'],$data['time_slot'],$cities['center'],$this->mid);
            foreach ($FreeCleaner as $cleaner) {
                WechatTemplateService::sendCleanerReceived($cleaner['openid'],$order['order_no'],$cities_member['contact_name'],$cities_member['contact_phone'],date('Y-m-d H:i:s'));
            }
            $this->success('订单创建成功！', ['order_no' => $order['order_no']]);
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $e) {
            $this->error("创建订单失败，请稍候再试！{$e->getMessage()}");
        }
    }

    /**
     * 获取订单支付参数
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function pay()
    {
        $data = $this->_input([
            'order_no' => $this->request->post('order_no'),
            'use_integral' => $this->request->post('use_integral'),//是否使用积分抵扣
            'enjoy' => $this->request->post('enjoy'),//是否下次接受此阿姨服务
            'subscribe' => $this->request->post('subscribe'),//是否下周同一时间下单
        ],[
            'order_no' => 'require|number',
            'use_integral' => 'accepted',
            'enjoy' => 'accepted',
            'subscribe' => 'accepted',
        ],[
            'order_no.require' => '请输入订单号！',
            'order_no.number' => '订单号格式错误！'
        ]);

        $order = Db::name('CleanOrder')
            ->where(['order_no' => $data['order_no']])
            ->find();
        if (empty($order)) $this->error('获取订单信息异常，请稍候再试！');
        if ($order['pay_state']) $this->error('订单已经完成支付，不需要再次支付！');
        if ($order['status'] <> 3) $this->error('该订单不能发起支付哦！');
        try {
            //支付前评价
            if($order['evaluate_status'] == '0')
            {
                //添加喜爱的保洁员
                if($data['enjoy'])
                {
                    if(Db::name('MemberEnjoy')->where([['mid','eq',$this->mid],['cid','eq',$order['cid']]])->count() < 1)
                    {
                        Db::name('MemberEnjoy')->insert(['mid' => $this->mid,'cid' => $order['cid']]);
                    }

                    //阿姨绑定地址 如果此地址没被绑定过
                    if(!Db::name('CitiesCleaner')->where('cities_id','eq',$order['cities_id'])->find())
                    {
                        Db::name('CitiesCleaner')->insert([
                           'cities_id' => $order['cities_id'],
                           'cid' => $order['cid']
                        ]);
                        //todo::插入模板消息
                    }
                }

                //下周同一时间下单
                if($data['subscribe'])
                {
                    $subscribe_order = [
                        'mid' => $this->mid,
                        'cid' => $order['cid'],
                        'order_no' => Data::uniqidNumberCode(12),
                        'service_date' => date('Y-m-d',strtotime($order['service_date'].' +1 week')),
                        'time_slot' => $order['time_slot'],
                        'cities_id' => $order['cities_id'],
                        'cities_center' => $order['cities_center'],
                        'service_duration' => $order['service_duration'],
                        'total_price' => $order['total_price'],
                        'status' => '2'
                    ];
                    Db::name('CleanOrder')->insert($subscribe_order);
                }
                $order['evaluate_status'] = '1';
                //是否使用积分
                $use_integral_num = 0;
                if($data['use_integral'])
                {
                    //查询用户当前积分
                    $integral = $this->member->integral;
                    //积分使用比例 默认为0
                    $service_integral_ratio = sysconf('service_integral_ratio') ?: 0;
                    //该订单可用积分最大值
                    $use_integral_num = floor($order['total_price'] * $service_integral_ratio);
                    //取可用的最小积分值
                    $use_integral_num = min($integral,$use_integral_num);
                    if($use_integral_num > 0)
                    {
                        $order['use_integral_num'] = $use_integral_num;
                        $order['integral_deduction_amount'] = $use_integral_num;
                        $order['discount_price'] = $use_integral_num;
                        $order['actual_amount'] = $order['total_price'] - $order['discount_price'];
                    }
                }
                Db::transaction(function() use($order,$use_integral_num){

                    if($use_integral_num > 0)
                    {
                        //减去积分数量
                        Db::name('Member')
                            ->where('id','eq',$this->mid)
                            ->setDec('integral',$use_integral_num);
                        //插入积分记录
                        Db::name('MemberIntegralLogs')->insert([
                            'mid' => $this->mid,
                            'number' => $use_integral_num,
                            'type' => 2,
                            'model' => 'clean',
                            'order_no' => $order['order_no'],
                            'content' => "服务订单【{$order['order_no']}】"
                        ]);
                        if($order['actual_amount'] == 0)
                        {
                            $order['status'] = '4';
                            $order['pay_state'] = '1';
                            $order['pay_type'] = 'integral';
                            $order['pay_at'] = date('Y-m-d H:i:s');
                        }
                    }
                    //修改订单状态
                    Db::name('CleanOrder')->where(['order_no' => $order['order_no']])->update($order);
                });
            }
            if($order['actual_amount'] > 0)
            {
                $this->success('获取订单支付参数成功！', ['pay_state' => '0','param' => $this->getPayParams($order['order_no'], $order['actual_amount'])]);
            } else {
                $this->success('订单支付成功！',['pay_state' => '1']);
            }

        } catch (HttpResponseException $exception) {
            throw  $exception;
        } catch (\Exception $e) {
            $this->error("获取订单支付参数失败，{$e->getMessage()}");
        }
    }

    /**
     * 获取订单支付参数
     * @param string $order_no
     * @param string $total_price
     * @return array
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     * @throws \think\Exception
     */
    protected function getPayParams($order_no,$total_price)
    {
        $options = [
            'body'             => '用户-服务订单支付',
            'openid'           => $this->member->openid,
            'out_trade_no'     => $order_no,
            'total_fee'        => $total_price * 100,
            'trade_type'       => 'JSAPI',
            'notify_url'       => url('api/v1/wx_notify', ['id' => 'clean'], false, true),
            'spbill_create_ip' => $this->request->ip(),
        ];
        $pay = WechatService::WePayOrder();
        $info = $pay->create($options);
        if ($info['return_code'] === 'SUCCESS' && $info['result_code'] === 'SUCCESS') {
            return $pay->jsapiParams($info['prepay_id']);
        }
        if (isset($info['err_code_des'])) {
            throw new \think\Exception($info['err_code_des']);
        } else {
            throw new \think\Exception('未知错误！');
        }
    }

    /**
     *  删除订单
     * @param $id
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function delete($id)
    {

        $where = [['order_no','eq',$id],['mid','eq',$this->mid],['status','in',['1','4']]];
        Db::name('CleanOrder')->where($where)->update(['is_deleted'=>'1']);
        $this->success('删除订单成功！');
    }

    /**
     * 取消订单
     * @param $id
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function cancel($id)
    {
        // 只有待接单订单可以取消
        $where = [['order_no','eq',$id],['mid','eq',$this->mid],['status','eq','1']];
        Db::name('CleanOrder')->where($where)->update(['status'=>'0']);
        //todo::取消订单提醒
        $this->success('取消订单成功！');
    }
}